import { useImperativeHandle, useRef } from 'react';
import { useUpdate } from 'ahooks';
import _cloneDeep from 'lodash/cloneDeep';

/**
 * 模态框及弹出框显示/隐藏hook
 * author: xugq
 * date: 2022-10-09
 *
 * api说明
 * hook支持传入一个ref对象并对该ref提供‘显示、隐藏、获取数据、设置数据’的api, 第二个参数为显示后需处理的事物
 * hook返回的变量说明：
 * record 传入的参数
 * visible 显示/隐藏变量
 * onHide 隐藏方法，传入回调代表隐藏后执行的事件
 * onCallBack 为ref对象的getData传入数据
 * onGetData 获取ref对象的setData传入的数据
 */

interface VisibleProps<T = any> {
  show: (record: T, fn?: () => void) => void
  hide: (fn?: () => void) => void
  setData: (data: T) => T
  getData: () => T
}

type T = any;

const useVisible = (handleRef: React.RefObject<VisibleProps>, func?: (data: T) => void) => {
  const update = useUpdate();

  const visibleRef = useRef(false);
  const dataRef: T = useRef();
  const callBackRef: T = useRef();
  const setDataRef: T = useRef();

  const options: VisibleProps = {
    show: (record, fn) => {
      dataRef.current = _cloneDeep(record);
      visibleRef.current = true;
      update();
      fn?.();
      func?.(dataRef.current);
    },
    hide: (fn) => {
      visibleRef.current = false;
      update();
      fn?.();
    },
    setData: data => (setDataRef.current = data),
    getData: () => callBackRef.current
  }

  const onCallBack = (data: T) => (callBackRef.current = data);

  const onGetData = () => setDataRef.current;

  useImperativeHandle(handleRef, () => options);

  return {
    record: dataRef.current,
    visible: visibleRef.current,
    onHide: options.hide,
    onCallBack,
    onGetData
  } as const;
};

export default useVisible;
